#include "NormalTable.h"
#include "StreamPacketBuilder.h"
#include "Protocal.h"
#include "TLog.h"
#include "DataBaseThread.h"
#include "ClientHandler.h"
#include "ActiveConnsList.h"
#include "GoodCardManager.h"
#include "TaskManager.h"
#include "Config.h"
#include "RoomManager.h"
#include "GameLotteryNew.h"

int NormalTable::test_card_num[6] = {0}; //好牌概率

NormalTable::NormalTable()
{
	m_timer.init( this );
	m_timer.cleanup();

	m_kick_timer.init( this );
	m_kick_timer.cleanup();

}

NormalTable::~NormalTable()
{

}

bool NormalTable::init( int table_id , RoomConfigItem * roomConf )
{
	m_base_chip = roomConf->base_gold ;
	m_cell_coin	= roomConf->cell_gold ;
	m_guo_di = roomConf->guo_di;
	return TableBase::init( table_id , roomConf );
}

bool NormalTable::joinTable( Player * player )
{
	bool ok = false ;
	for ( BYTE i = 0 ; i < TABLE_CHAIR_COUNT ; i++){
		if ( m_table_players [ i ] == NULL ){
			player->sitDown( this , i );
			m_total_players ++ ;
			m_table_players [ i ] = player ;
			if ( m_table_players[i]->isNormalPlayer() )
			{
				m_real_playernum++;
			}
			ok = true ;
			break;
		}
	}
	//printf( "zq joinTable uid=%u  ok = %d\r\n", player->get_user_id(), ok );
	if ( ok )
	{
		for ( BYTE i = 0 ; i < GAME_PLAYER; i++)
		{
			if ( m_table_players [ i ] )
			{
				Player * player = m_table_players [ i ];
				if(i != m_table_players [ i ]->get_chair_id() || m_table_id != m_table_players [ i ]->get_table_id())  //!???????
				{
					//WL(LL_WARNING,"joinTable checkStart i != player->get_chair_id() userID::%d  table_id = %d  i:%d  get_chair_id:%d  get_table_id:%d \n",player->get_user_id(), m_table_id, i, player->get_chair_id(), player->get_table_id());
					m_table_players[ i] = NULL;
				}
			}
		}
		player->reflashStayTableTime();
		//printf( "table_id = %d player = %u sitdown chair = %d ok \n",m_table_id , player->get_user_id() , player->get_chair_id() );
		StreamPacketBuilder::instance()->respEnterRoom( player );
		StreamPacketBuilder::instance()->notifyPlayerJoin( this , player );
	}
	else 
	{
		WL(LL_INFO,"table_id = %d player = %u  sitdown chair = %d faild m_total_players = %d\n",
			m_table_id , player->get_user_id() , player->get_chair_id() , m_total_players );
		StreamPacketBuilder::instance()->respError( player , MSG_RESP_ENTER_ROOM , ERR_FULL_ROOM );
		return false;
	}
	StreamPacketBuilder::instance()->PrintLog( player->get_user_id(), "EnterRoom uid : %u tableid : %d  result : %d", player->get_user_id(), getTableId(), ok );
#ifdef SHOW_DETIAL 
	 WL(LL_ERROR, "EnterRoom uid : %u table_id : %d  result : %d chair = %d  player addr:0x%02x \n", player->get_user_id(), getTableId(), ok , player->get_chair_id(), player);
#endif

	if(! player->get_handler())
		return false;

	player->get_handler()->changeUserOnlineStatus(getRoomConf()->room_id,player->get_user_id());

	player->check_robot_gold();	
	return ok ;
}

bool NormalTable::leaveTable( Player * player, int type )
{
	//printf( "leaveTable================================\r\n" );
	if ( vaildChair( player->get_chair_id() ) )
	{
		BYTE chair =  player->get_chair_id() ;
		if ( isPlaying() ) //正在游戏
		{
			StreamPacketBuilder::instance()->PrintLog( player->get_user_id(), "table playing leave table tableid = %d", player->get_table_id() );
			if ( player->isPlaying() ) //正在游戏
			{
				if ( isCurrChair( player->get_chair_id() ) )
				{
					m_curr_chair = nextChair( m_curr_chair );
					resetRound();
				}
				recordPlayerLost( player ) ;
				StreamPacketBuilder::instance()->notifyPlayerGiveup( this , player , true ) ;
			}
			if ( player->get_chair_id() == m_start_round_chair ){
				m_start_round_chair = nextChair( m_start_round_chair );
			}
			StreamPacketBuilder::instance()->notifyStatusChange( this , player , STATUS_LEAVE_CHAIR ) ;
			playerLeaveTable( player );
			resetRunInfo() ; //
	#ifdef SHOW_DETIAL 
			WL(LL_INFO,"table_id = %d player = %d game playing leave chair = %d , %d playing = %d total = %d  player addr:0x%02x \n",
				m_table_id , player->get_user_id() , chair , player->get_chair_id(),m_playing_count , m_total_players, player );
	#endif
			if ( m_playing_count <= 1 ) this->gameOver();
		}
		else
		{
			//printf( "zq player->get_chair_id() = %d m_banker_user = %d\r\n", player->get_chair_id(), m_banker_user );
			StreamPacketBuilder::instance()->PrintLog( player->get_user_id(), "table idle leave table tableid = %d", player->get_table_id() );
			if ( player->get_chair_id() == m_banker_user )
			{
				m_banker_user = INVALID_CHAIR;
			}
			StreamPacketBuilder::instance()->notifyStatusChange( this , player , STATUS_LEAVE_CHAIR ) ;
	
			playerLeaveTable( player );

	#ifdef SHOW_DETIAL 
			WL(LL_INFO,"table_id = %d player = %d leave chair = %d ,%d  ready = %d count = %d player addr:0x%02x \n",
				m_table_id , player->get_user_id() ,chair , player->get_chair_id(),m_ready_count , m_total_players , player);
	#endif
	
			checkStart();
		}
		return true ;
	}
	else
	{
		return false ;
	}
}


bool NormalTable::SystemKickPlayer( Player * player )
{
	if ( vaildChair( player->get_chair_id() ) )
	{
		BYTE chair =  player->get_chair_id() ;
		if ( isPlaying() ) //正在游戏
		{
			return false;
		}
		else
		{
			StreamPacketBuilder::instance()->notifySystemPleaseLeave( player );
			playerLeaveTable( player );
			checkStart();
			if(! player->get_handler())
				return false;
			if(GameLotteryNew::instance()->isPlayerInBetStatus(player->get_user_id()) ==  false)
			{
				player->get_handler()->changeUserOnlineStatus(0,player->get_user_id());
			}
		}
		return true ;
	}
	return false ;
}

bool NormalTable::handlePacket( Packet* packet , Player * player )
{
	switch ( packet->cmd )
	{
	case MSG_REQ_LOOK_CARD:
		//printf( "zq MSG_REQ_LOOK_CARD\r\n" );
		this->lookCard( player );
		break;
	case MSG_REQ_GAME_READY:
		this->ready( player );
		break;
	case MSG_REQ_ADD_SCORE:
		//printf( "zq MSG_REQ_ADD_SCORE\r\n" );
		handleAddScore( packet , player );
		break;
	case MSG_REQ_COMPARE_CARD:
		//printf( "zq MSG_REQ_COMPARE_CARD\r\n" );
		handleCmpCard( packet , player );
		break;
	case MSG_REQ_GIVE_UP:
		//printf( "zq MSG_REQ_GIVE_UP\r\n" );
		this->giveup( player );
		break;	
	case MSG_REQ_ALLIN:
		//printf( "zq MSG_REQ_ALLIN\r\n" );
		this->allIn( player );
		break;
	case MSG_REQ_CHAT:
		handleTextChat( packet , player );
		break;
	case MSG_REQ_PAY_EXPRESSION:
		handleReqPayExpress( packet , player );
		break;
	case MSG_REQ_REWARD_COIN:
		handleRewardOnlineCoin( packet , player );
		break;
	case MSG_REQ_ONLINE_REWARD_CONF:
		handleOnlineRewardConf( packet , player );
		break;
	case MSG_REQ_ONLINE_REWARD_STATUS:
		handleOnlineRewardStatus( packet , player );
		break;
	case MSG_REQ_USE_PROP:
		handleUseProps( packet , player );
		break;
	case MSG_REQ_KICK_PLAYER:
		handleKickPlayer( packet , player );
		break;
	case MSG_REQ_LEAVE_ROOM:
	case MSG_REQ_LEAVE_CHAIR:
		this->leaveTable( player );
		break;
	default:
		WL(LL_WARNING,"unkown game cmd = 0x%02x\n",packet->cmd );
		break;
	}
	return true ;
}

void NormalTable::update()
{
	if ( m_total_players > 0 )
	{
		m_timer.heartbeat();
	}
}

void NormalTable::ready( Player * player )
{
	SystemMantainConfig* pSysMantainMsg = Config::instance()->get_mantain_time();	
	if ( pSysMantainMsg )
	{
		//printf( "zq ready pSysMantainMsg = %x\r\n", pSysMantainMsg );
		StreamPacketBuilder::instance()->respError(player ,MSG_RESP_GAME_READY , ERR_SYSTEM_REPAIR, pSysMantainMsg->message  );
		return ;
	}

	if ( isPlaying()  ) 
	{
		StreamPacketBuilder::instance()->respError(player ,MSG_RESP_GAME_READY , ERR_READY_STATUS_PLAYING  );
		return ;
	}

	if ( player->isReady() ) {
		StreamPacketBuilder::instance()->respError(player ,MSG_RESP_GAME_READY , ERR_READY_STATUS_READY  );
		return ;
	}

	//printf( "table_id = %d player = %d chair = %d ready = %d coin = %lld\n",m_table_id , player->get_user_id() , player->get_chair_id(),m_ready_count ,player->get_user_gold() );
	if (  player->get_user_gold() < m_room_config->guo_di)
	{
		StreamPacketBuilder::instance()->respError(player ,MSG_RESP_GAME_READY , ERR_READY_NO_GOLD  );
		return  ;
	}
	player->ready();
	m_ready_count ++ ;
	//printf( "table_id = %d player = %d chair = %d ready = %d coin = %lld\n",
		//m_table_id , player->get_user_id() , player->get_chair_id(),m_ready_count ,player->get_user_gold() );
	StreamPacketBuilder::instance()->notifyStatusChange( this , player , STATUS_READY );
	checkStart();

}

void NormalTable::UpdatePlayerHongbaoTask( Player * player1, Player *player2 )
{
	if (getRoomConf())
	{
		int roomid = getRoomConf()->room_id;
		switch (roomid)
		{
			case ROOM_CONFI_ID_1:
				// if (player1)
				// 	player1->UpdateHongbaoTask(SANZHANG_CHUJI_WANPAI);
				// if (player2)
				// 	player2->UpdateHongbaoTask(SANZHANG_CHUJI_WANPAI);
				break;
			case ROOM_CONFI_ID_2:
				if (player1)				
					player1->UpdateHongbaoTask(HONGBAO_TASK_SANZHANG, 1, 1);
				if (player2)
					player2->UpdateHongbaoTask(HONGBAO_TASK_SANZHANG, 1, 1);
				break;
			case ROOM_CONFI_ID_3:
				if (player1)				
					player1->UpdateHongbaoTask(HONGBAO_TASK_SANZHANG, 2, 1);
				if (player2)				
					player2->UpdateHongbaoTask(HONGBAO_TASK_SANZHANG, 2, 1);
				break;
			case ROOM_CONFI_ID_4:
				// if (player1)				
				// 	player1->UpdateHongbaoTask(SANZHANG_SIREN_WANPAI);
				// if (player2)				
				// 	player2->UpdateHongbaoTask(SANZHANG_SIREN_WANPAI);
				break;
			case ROOM_CONFI_ID_5:
				if (player1)				
					player1->UpdateHongbaoTask(HONGBAO_TASK_SANZHANG, 3, 1);
				if (player2)			
					player2->UpdateHongbaoTask(HONGBAO_TASK_SANZHANG, 3, 1);
				break;
		}
	}
}

void NormalTable::giveup( Player * player )
{
	//printf("zq giveup tableid = %d userid = %d\r\n", getTableId(),  player->get_user_id() );
	if ( isPlaying() && player->isPlaying() )
	{
		player->giveup();
		resetRunInfo();
		recordPlayerLost( player ) ;

//		UpdatePlayerHongbaoTask(player, NULL);		
		
		if ( m_playing_count <= 1 ){ 
			StreamPacketBuilder::instance()->notifyPlayerGiveup( this , player );
			this->gameOver();
		}
		else{
			if ( isCurrChair( player->get_chair_id()) ) 
			{
				//printf( "giveup ***** m_curr_chair = %d\r\n", m_curr_chair );
				m_curr_chair = nextChair( m_curr_chair );
				//printf( "giveup ===== m_curr_chair = %d\r\n", m_curr_chair );
				resetRound();
				startOperaTimer();
				
			}
			if ( player->get_chair_id() == m_start_round_chair ){
				m_start_round_chair = nextChair( m_start_round_chair );
			}
			//printf( "giveup ############## m_curr_chair = %d\r\n", m_curr_chair );
			StreamPacketBuilder::instance()->notifyPlayerGiveup( this , player );
			if ( isCurrChair( player->get_chair_id()) ) 
			{
				roundOver();
			}
		}
	}
	else
	{
		//printf("zq giveup table_id = %d player = %d give up faild game statsu = %d user_status=%d\n",
		//		m_table_id ,player->get_user_id() , isPlaying() , player->get_user_status() );
	}
}

void NormalTable::lookCard( Player * player )
{
	/*???????*/
	if(m_room_config->room_id == ROOM_CONFI_ID_8)
		return;
	if ( isPlaying() && player->isPlaying() && !player->isLookCard() )
	{
		player->lookCard();
		//WL(LL_DEV ,"table_id = %d player = %u chair = %d look card\n",m_table_id ,player->get_user_id(), player->get_chair_id());
		int card_type = m_game_logic.get_card_type_sort( player->getCards(), MAX_COUNT);
		StreamPacketBuilder::instance()->notifyLookCard( this , player, card_type );
	}
	else
	{
		//WL(LL_WARNING ,"table_id = %d player = %d look faild game statsu = %d user_status=%d\n",m_table_id ,player->get_user_id() , isPlaying() , player->get_user_status() );
		StreamPacketBuilder::instance()->respError(player ,MSG_RESP_LOOK_CARD , ERR_UNKOWN  );
	}
}

bool NormalTable::cmpCard( Player * player , Player * dstPlayer )
{
	if(player == NULL || dstPlayer == NULL)
	{
		return false;
	}
	if ( !isPlaying() || !player->isPlaying()  || !isCurrChair( player->get_chair_id() ) || !dstPlayer->isPlaying() ) 
	{
		StreamPacketBuilder::instance()->respError(player ,MSG_RESP_COMPARE_CARD , ERR_UNKOWN  );
		return false ;
	}

//	UpdatePlayerHongbaoTask(player, dstPlayer);
	BYTE card_type [ 2 ] = { 0 } ;
	//比较大小
	bool ret = m_game_logic.compare_card( player->getCards() ,dstPlayer->getCards() ,MAX_COUNT , card_type);
	Player * winPlayer	= ret ? player : dstPlayer ;
	Player * lostPlayer	= ret ? dstPlayer : player ;
	systemGiveTicket( winPlayer->get_chair_id() , lostPlayer->get_chair_id() , card_type ) ;
	int allin_coin	  = 0 ;
	for (BYTE i = 0; i < GAME_PLAYER; i++){
		if ( m_table_players[ i ] && m_table_players[ i ]->isPlaying() ) {
			if ( m_table_players[ i ]->m_allin_coin > 0 ) 
				allin_coin = m_table_players[ i ]->m_allin_coin;
		}
	}
	DWORD compare_gold = 0 ;
	if ( player->isLookCard() ) {
		//如果是看牌状态,当前金币*4
		compare_gold = m_current_coin * 4 ;
	}else{
		//如果是没看牌状态,当前金币*2
		compare_gold = m_current_coin * 2 ;
	}
	if ( allin_coin > 0 ) 
	{
		compare_gold = allin_coin ;
	}
	//修正,如果余额比这个小
	INT64 sparegold = player->get_user_gold() - ( player->getTableCoin() + compare_gold );
	if ( sparegold  >= 0  )
	{
		player->setTableCoin( player->getTableCoin() +  compare_gold ) ;
	}
	else
	{
		compare_gold = player->get_user_gold() - player->getTableCoin() ;
		player->setTableCoin( player->get_user_gold() ) ;
	}

	m_total_coin += compare_gold ;
	
	if ( hasAllIn() )
	{
		m_allin_compare = 2;//all in并比牌了
		//printf( "zq =========m_allin_compare = true\r\n" );
	}

	//printf( "zq cmpCard success ****cmpare m_total_coin = %d compare_gold = %d\r\n", m_total_coin, compare_gold );

	lostPlayer->lost(); // 失败
	
	//处理输的玩家
	recordPlayerLost( lostPlayer );
	
	//下一个用户
	m_curr_chair = nextChair( m_curr_chair );
	resetRound(); 
	
	//比牌输了之后要更新第一个跟注的位置,要不轮数不变
	if ( lostPlayer->get_chair_id() == m_start_round_chair ){
		m_start_round_chair = nextChair( m_start_round_chair );
	}
	StreamPacketBuilder::instance()->notifyCmpCard( this , player , dstPlayer , lostPlayer , compare_gold, (lostPlayer == player) ? false : true ) ;

	resetRunInfo();
	//printf( "zq m_current_coin = %d compare_gold=%d, tablecoin=%d usergold=%d, totalgold=%d m_playing_count = %d hasAllIn() = %d\r\n", 
	//	m_current_coin, compare_gold ,player->getTableCoin() , player->get_user_gold(),m_total_coin, m_playing_count, hasAllIn() );
	//结束游戏
	if ( m_playing_count < 2 )
	{
		this->gameOver();
	}
	else
	{
		startOperaTimer();
	}
	roundOver();
}

bool NormalTable::addScore( Player * player , int score , BYTE is_add, BYTE times /*= 0 */ )
{
	int userid = player->get_user_id();
	if ( !isPlaying() || !player->isPlaying() )
	{
		//printf( "zq addScore error userid = %d is not playing isPlaying() = %d player->isPlaying() = %d is_add = %d\r\n", userid, isPlaying(), player->isPlaying(), is_add );
		StreamPacketBuilder::instance()->respError(player ,MSG_RESP_ADD_SCORE , ERROR_ADDSCORE_NO_PLAYINT  );
		return false;
	}
	if ( !isCurrChair( player->get_chair_id() ) )
	{
		//printf( "zq addScore error userid = %d  curid = %d  playercid = %d is_add = %d\r\n", userid, m_curr_chair, player->get_chair_id(), is_add );
		StreamPacketBuilder::instance()->respError(player ,MSG_RESP_ADD_SCORE , ERROR_ADDSCORE_NO_TURN  );
		return false;
	}
	if ( m_current_round >= m_room_config->max_round )
	{
		//printf( "zq addScore error userid = %d  curround = %d  maxround = %d is_add = %d\r\n", userid, m_current_round, m_room_config->max_round, is_add );
		//StreamPacketBuilder::instance()->respError(player ,MSG_RESP_ADD_SCORE , ERROR_ADDSCORE_MAX_ROUND  );
		//return false ;
	}

	int chipsisok = false;
	for ( int i = 0; i < 5; i++ )
	{
		if( m_room_config->chips_code[i] == score )
		{
			chipsisok = true;
			break;
		}
	}
	if ( chipsisok == false )
	{
		printf( "zq addScore error userid = %d  score = %d maxcore = %d  curships  = %d chipsisok = false  %d %d %d %d %d is_add = %d \r\n", 
			userid, score, m_room_config->max_cell_gold, getCurrCoin(), m_room_config->chips_code[0], m_room_config->chips_code[1],
			m_room_config->chips_code[2], m_room_config->chips_code[3], m_room_config->chips_code[4], is_add);
	}
	
	//判断筹码正确性
	if ( chipsisok == false ) //score <= 0 || score > m_room_config->max_cell_gold )
	{	
		if ( is_add == false )
		{
			score = getCurrCoin();
			//printf( "zq addScore error 1 userid = %d  score = %d maxcore = %d curchips = %d is_add = %d\r\n", userid, score, m_room_config->max_cell_gold, getCurrCoin(), is_add );
		}
		else
		{
			//printf( "zq addScore error 2 userid = %d  score = %d maxcore = %d curchips = %d is_add = %d\r\n", userid, score, m_room_config->max_cell_gold, getCurrCoin(), is_add );
			StreamPacketBuilder::instance()->notifyTableChips( player->getTable(), player );
			StreamPacketBuilder::instance()->respError(player ,MSG_RESP_ADD_SCORE , ERROR_ADDSCORE_CHIPS_ERR  );
			return false ;
		}
		
	}
	//跟注 筹码在列表里面,但是不对
	if ( (is_add == false) && (getCurrCoin() != score)  && m_current_round >= 1)
	{
		//printf( "zq addScore error 3 userid = %d  score = %d maxcore = %d curchips = %d is_add = %d\r\n", userid, score, m_room_config->max_cell_gold, getCurrCoin(), is_add );
		score = getCurrCoin();
	}

	if(chipsisok && is_add == true && m_current_round >= 1)  
	{
		if(score < m_current_coin)
		{
			score = m_current_coin;
		}
	}
	if ( hasAllIn() )
	{
		//printf( "zq addScore error userid = %d is_add = %d is allin \r\n", userid, is_add );
		StreamPacketBuilder::instance()->respError(player ,MSG_RESP_ADD_SCORE , ERROR_ADDSCORE_IS_ALLIN  );
		return false;
	}
	int coin = score;
	if ( player->isLookCard() ) {
		coin = score * 2 ;
	}else coin = score ;
	
	if (( coin + player->getTableCoin() ) > player->get_user_gold() )
	{
		
		//printf( "zq addScore error userid = %d  needscore = %d usergold = %d is_add = %d\r\n", userid, coin + player->getTableCoin(), player->get_user_gold(), is_add );
		StreamPacketBuilder::instance()->respError(player ,MSG_RESP_ADD_SCORE , ERROR_ADDSCORE_LESS_GOLD  );
		return false ;
	}
	//m_current_coin = score > m_current_coin ? score : m_current_coin ;
	m_current_coin = score ;

	player->setTableCoin( player->getTableCoin() + coin );
	m_total_coin += coin ;
	//下一个用户
	m_curr_chair = nextChair( m_curr_chair );
	resetRound(); 

	//printf("zq addScore success   table_id = %d player = %u add gold = %d table=%d total = %lld current=%d curr_chair=%d op=%d total_coin=%d\n",m_table_id ,
	//	player->get_user_id() ,coin ,player->getTableCoin() ,player->get_user_gold() ,m_current_coin , m_curr_chair , m_current_round ,m_total_coin );
	StreamPacketBuilder::instance()->notifyAddCoin( this , player , coin, is_add );
	startOperaTimer();
	roundOver();

}

void NormalTable::allIn( Player * player )
{
	if ( !isPlaying() || !player->isPlaying() || player->isAllIn() || !isCurrChair( player->get_chair_id() ) ) 
	{
		StreamPacketBuilder::instance()->respError(player ,MSG_RESP_ALLIN , ERR_UNKOWN  );
		return ;
	}
	if ( hasAllIn() )
	{
		StreamPacketBuilder::instance()->respError(player ,MSG_RESP_ALLIN , ERR_UNKOWN  );
		return  ;
	}
	Player * secondPlayer = NULL ;
	m_playing_count = 0 ;
	for (BYTE i = 0; i < GAME_PLAYER; i++){
		if ( m_table_players[ i ] && m_table_players[ i ]->isPlaying() ) {
			m_playing_count ++;
			if ( i != player->get_chair_id() ) secondPlayer = m_table_players[ i ] ;
		}
	}
	if ( m_playing_count > 2 || secondPlayer == NULL )
	{
		StreamPacketBuilder::instance()->respError(player ,MSG_RESP_ALLIN , ERR_UNKOWN  );
		return  ;
	}

	INT64 first_remain	= player->get_user_gold() - player->getTableCoin() ;
	INT64 second_remain	=  secondPlayer->get_user_gold()  - secondPlayer->getTableCoin() ;
	INT64 coin			= first_remain > second_remain ? second_remain : first_remain ;

	//全压金币有上限处理
	if ( coin > 2000000000  )
	{
		coin = 2000000000;
	}

	player->m_allin_coin = coin  ;
	player->setTableCoin( coin + player->getTableCoin() );
	player->allIn();

	m_total_coin += player->m_allin_coin ;
	m_allin_compare = 1;
	//下一个用户
	m_curr_chair = nextChair( m_curr_chair );
	resetRound(); 
	/*
	printf(
		"allIn success  table_id = %d player = %u allin = %d user_gold = %lld table_coin=%d sencond = %u user_gold = %d table_coin=%d  current=%d curr_user=%d op=%d total_coin=%d\n",
		m_table_id ,player->get_user_id() ,player->m_allin_coin ,player->get_user_gold() ,player->getTableCoin() ,
		secondPlayer->get_user_id() ,secondPlayer->get_user_gold(),secondPlayer->getTableCoin() , 
		m_current_coin , m_curr_chair , m_current_round ,m_total_coin); */
	StreamPacketBuilder::instance()->notifyAllin( this , player , player->m_allin_coin );
	startOperaTimer();
}

void NormalTable::gameStart()
{
	printf("NormalTable::gameStart \n");
	m_table_status	= GAME_STATUS_PLAYING ;
	m_current_round = 0 ; //当前轮数
	//m_current_coin  = m_cell_coin;
	m_current_coin = m_guo_di;
	m_total_coin	= 0 ;
	m_start_round_chair = 0 ;
	//m_banker_user	= INVALID_CHAIR;
	m_ready_count	= 0 ;
	m_total_players = 0 ;
	m_ready_count = 0;
	m_playing_count = 0 ;
	m_kick_timer.cleanup();
	m_timer.cleanup();
	m_allin_compare = 0;
	m_real_playernum = 0;
	//游戏局数
	int *ptr = (int*)&m_gameid;
	ptr[0] = time(NULL);
	ptr[1] = (m_room_config->room_id<<16) + m_table_id;//留着以后在用

	//printf( "zq gamid = %llx  m_table_id=%x, m_room_config->room_id = %x time(NULL)=%x\r\n", m_gameid,  m_table_id, m_room_config->room_id, time(NULL) );
	//分发扑克
	memset( m_res_cards, 0, sizeof(m_res_cards) );
	m_game_logic.rand_card_list( m_res_cards, sizeof( m_res_cards ) );//BYTE类型

	//m_game_logic.rand_card_list( m_player_card_data[ 0 ],sizeof( m_player_card_data )/sizeof(m_player_card_data[0][0]));

	//好牌概率
	//sendGoodCards() ;

	BYTE	user_type [ TABLE_CHAIR_COUNT ] ;
	for ( BYTE i = 0 ; i < TABLE_CHAIR_COUNT ; i++){
		user_type [ i ] = INVALID_BYTE ;
		m_ticket  [ i ]  = 0 ;
		if ( m_table_players [ i ] ) {
			m_total_players ++ ;
			if ( m_table_players[i]->isNormalPlayer() )
			{
				m_real_playernum++;
			}
			m_table_players [ i ]->m_allin_coin = 0 ;
			m_table_players [ i ]->m_table_coin = 0 ;
			//memcpy( m_table_players [ i ]->m_cards , m_player_card_data[ i ] , MAX_COUNT );
			user_type [ i ]				= m_table_players [ i ]->getUserType() ;
			if ( m_table_players [ i ]->isReady() )
			{
				m_table_players [ i ]->startGame();
				m_playing_count ++ ;
				m_table_players [ i ]->setTableCoin( m_guo_di );
				m_total_coin += m_guo_di ;
				m_table_players [ i ]->setNoPlayTime();//开局重置时间
				UpdatePlayerHongbaoTask(m_table_players[i], NULL);		
				//printf( "zq ****start game m_total_coin = %d\r\n", m_total_coin );
				//printf( "ready : %d", i );
			}
			else
			{
			//	printf( "no ready : %d", i );
				if( m_banker_user == i )
				{
					m_banker_user = INVALID_CHAIR;
				}
			}
		}
	}
#ifdef SHOW_DETIAL 
	for ( BYTE i = 0 ; i < TABLE_CHAIR_COUNT ; i++){
		if ( m_table_players [ i ] ) {
			WL(LL_DEV ,"i = %d table_id = %d player = %d is game start total_player = %d playing=%d status = %d coin=%d tableCoin=%d totalTable=%d\n",
				i, m_table_id ,m_table_players [ i ]->get_user_id() ,m_total_players , m_playing_count ,
				m_table_players [ i ]->get_user_status() ,m_table_players [ i ]->get_user_gold() ,m_table_players [ i ]->getTableCoin() ,m_total_coin );
		}
	}
#endif
	//确定庄家
	setDeader();

	//从庄家开始发牌
	int startchairid = m_banker_user;
	int cardpos = 0;
	for ( BYTE i = 0 ; i < TABLE_CHAIR_COUNT*3 ; i++)//分三轮发牌
	{
		BYTE chair =  ( startchairid + i ) % TABLE_CHAIR_COUNT ;
		//m_playing_count
		if ( m_table_players [ chair ] && m_table_players [ chair ]->isPlaying() )
		{
			m_player_card_data[chair][i/TABLE_CHAIR_COUNT] = m_res_cards[ cardpos++ ];
			
		}
	}
	//测试固定发牌
#if 0
	memset( m_player_card_data[ 0 ], 0, sizeof( m_player_card_data )/sizeof(m_player_card_data[0][0]) );
	BYTE player_card_data[TABLE_CHAIR_COUNT][MAX_COUNT] = 
	{
		{	0x01,0x11, 0x21	},
		{	0x02,0x03, 0x04	},
		{	0x12,0x13, 0x25	},
		{	0x3b,0x3a, 0x35	},
		{	0x18,0x19, 0x17	},
	};

	BYTE szTmp[3] = {0};
	srand((unsigned)time(NULL)+ m_table_id);
	for(BYTE idx = 0; idx < 5; idx++)
	{
		memset(szTmp, 0, 3);
		int value =  (0 + rand()%(4 - 0 +1));
		memcpy(szTmp, player_card_data[value],   3);
		memcpy(player_card_data[value], player_card_data[idx],   3);
		memcpy(player_card_data[idx], szTmp,   3);
		
	}
	memcpy( m_player_card_data, player_card_data, sizeof( m_player_card_data )/sizeof(m_player_card_data[0][0]) );
#endif
	for ( BYTE i = 0 ; i < TABLE_CHAIR_COUNT; i++)
	{
		if ( m_table_players [ i ] && m_table_players [ i ]->isPlaying() )
		{
			memcpy( m_table_players [ i ]->m_cards , m_player_card_data[ i ] , MAX_COUNT );
		}
	}

#if 0
	//test  打印牌
	printf( "==========  统计牌  =========\r\n" );
	for ( int i = 0; i < 52; i++ )
	{
		if ( (i > 0) && ((i % 13) == 0) )
		{
			printf( "\r\n" );
		}
		printf( "%x ", m_res_cards[i] );
	}
	printf( "\n" );
	BYTE sendcards[15] = {0};
	BYTE loop = 0;
	for ( int i = 0; i < TABLE_CHAIR_COUNT; i++ )
	{
		BYTE chair =  ( startchairid + i ) % TABLE_CHAIR_COUNT ;
		if ( m_table_players [ chair ] && m_table_players [ chair ]->isPlaying() )
		{
			int cardtype = m_game_logic.get_card_type( m_player_card_data[chair], 3 );
			test_card_num[cardtype-1]++;
			sendcards[loop++];
			printf( "chairid : %d  cards : %02x %02x %02x  isbanker : %d  userid : %d  bankerid = %d\r\n", 
				chair, m_player_card_data[chair][0], m_player_card_data[chair][1], m_player_card_data[chair][2], chair == m_banker_user, m_table_players [ chair ]->get_user_id(), m_banker_user );
			
		}
		
	}
	if( strncmp( (char*)m_res_cards, (char*)sendcards, strlen((char*)sendcards) ) != 0 )
	{
		printf( "********************* error ***********************\r\n" );
	}
	printf( "==========  统计牌  =========\r\n" );
	int totalnum = test_card_num[0] + test_card_num[1] + test_card_num[2] + test_card_num[3] + test_card_num[4] + test_card_num[5];
	printf( "%d %d %d %d %d %d %04d %04d %04d %04d %04d %04d \r\n", 
		test_card_num[0], test_card_num[1], test_card_num[2], test_card_num[3], test_card_num[4],test_card_num[5],
		test_card_num[0]*1000/totalnum, test_card_num[1]*1000/totalnum, test_card_num[2]*1000/totalnum, test_card_num[3]*1000/totalnum, test_card_num[4]*1000/totalnum,test_card_num[5]*1000/totalnum );
#endif

	m_curr_chair = nextChair(m_banker_user);
	m_start_round_chair = m_curr_chair ;

#ifdef SHOW_DETIAL 

	WL(LL_DEV ,"table_id = %d is game start total_player = %d playing=%d banker = %d  urrChair=%d\n",
		m_table_id ,m_total_players , m_playing_count , m_banker_user ,m_curr_chair  );
#endif

	StreamPacketBuilder::instance()->notifyGameStart( this , (BYTE*)m_player_card_data , user_type );
	startOperaTimer();
}

void NormalTable::gameOver()
{
	m_table_status = GAME_STATUS_INDL ;
	DWORD winner_score	= 0 ;
	INT64 beforetaxgold = m_total_coin;
	BYTE winner = INVALID_BYTE ;
	BYTE losener = 0;
	INT64 totalxzgold = m_total_coin;
	m_total_players = 0 ;
	m_real_playernum = 0;
	m_ready_count   = 0 ; //准备的人清0
	//m_banker_user			= INVALID_CHAIR;					//大盲注位置
	m_curr_chair			= INVALID_CHAIR;						//当前操作玩家
	m_current_round			= 0 ;
	m_current_coin			= 0 ;
	
	m_start_round_chair		= 0 ;
	m_ready_count			= 0 ;
	m_playing_count			= 0 ;
	GameEndData game_end_data;
	//不能是winner_score去算玩家输赢金币:玩家离桌后把用户清除了,不可能计算的到
	for ( BYTE i = 0 ; i < TABLE_CHAIR_COUNT; i++) 
	{
		m_total_players +=  m_table_players [ i ] ? 1 : 0 ;
		if ( m_table_players[i] && m_table_players[i]->isNormalPlayer() )
		{
			m_real_playernum++;
		}
		if ( m_table_players[i] )
		{
			m_table_players[i]->check_robot_gold();
		}
		
		game_end_data.result_info [ i ].balance = 0 ;
		game_end_data.result_info [ i ].score	= 0 ;
		game_end_data.result_info [ i ].ticket	= 0 ;
		memcpy( game_end_data.result_info [ i ].card_data , m_player_card_data [ i ] , MAX_COUNT );
		
		if ( m_table_players [ i ] && !m_table_players [ i ]->isIndle() )
		{
			if ( m_table_players [ i ]->isPlaying() )
			{
				//winner = m_table_players [ i ]->get_chair_id();
				winner = i;
				//printf( "zq winner tablegold = %d m_allin_coin=%d  m_allin_compare = %d\r\n", m_table_players [ i ]->getTableCoin(), m_table_players[i]->m_allin_coin, m_allin_compare );
				winner_score += m_table_players [ i ]->getTableCoin() ;//自己下注的钱也算上
				//如果是allin 一方放弃则不算税收
				if (0)//( m_allin_compare == 1 )
				{
					beforetaxgold -= m_table_players[i]->m_allin_coin;
				}
				continue;
			}
			INT64 bal = m_table_players [ i ]->get_user_gold();
			bal		= bal < 0 ? 0 : bal ;
			game_end_data.result_info [ i ].balance = bal ;
			game_end_data.result_info [ i ].score	= HTONL( - m_table_players [ i ]->getTableCoin() );
			winner_score += m_table_players [ i ]->getTableCoin() ;
			//printf( "zq for uid = %u gold = %lld winner_score = %d  tablecoin=%d\r\n", m_table_players [ i ]->get_user_id(), bal,  winner_score, m_table_players [ i ]->getTableCoin() );
		}
	}
	m_banker_user = winner;					//大盲注位置

	if(INVALID_BYTE == winner)
	{
		WL(LL_WARNING,"INVALID_BYTE == winner  \n");
		return;
	}
	//处理税收
	DWORD	tax_rate							=	m_room_config->tax_rate;
	DWORD	winner_tax	= 0;
	if(m_room_config->room_id == ROOM_CONFI_ID_8)
	{
		winner_tax =(beforetaxgold - m_table_players[winner]->getTableCoin() )* tax_rate /100;
		
	}
	else
	{
		winner_tax	=	beforetaxgold * tax_rate /100;
	}
	totalxzgold								-=  winner_tax ;
	game_end_data.winner_tax					=	HTONL( winner_tax );
	game_end_data.result_info[ winner ].score	=	HTONL( totalxzgold );
	game_end_data.result_info[ winner ].balance	=	HTONLL( m_table_players [ winner ]->get_user_gold()  + totalxzgold - m_table_players [ winner ]->getTableCoin() ) ;
	//printf( "zq totalxzgold = %d winner_tax=%d  winnergold = %lld balance=%lld beforetaxgold=%d\r\n", totalxzgold, winner_tax, m_table_players [ winner ]->get_user_gold(), game_end_data.result_info[ winner ].balance, beforetaxgold );
	finishTask();
	int ticket = rewardTicket( m_table_players [ winner ] , winner_tax  ) ;
	//写入积分
	for ( BYTE i = 0 ; i < GAME_PLAYER; i++) {
		if ( m_table_players [ i ]  ){
			if ( m_table_players [ i ]->isPlaying()  ){
				if ( i == winner ) 
					recordPlayerWin( m_table_players [ i ] , totalxzgold - m_table_players [ winner ]->getTableCoin() , winner_tax , ticket, beforetaxgold  ) ;
 				else 
 					OnGameOverPlayerLost( m_table_players [ i ], m_table_players[winner] ) ;
			}
			else {
				if (m_table_players [ i ]->isNeedWriteLost())
					OnGameOverPlayerLost( m_table_players [ i ], m_table_players[winner] ) ;
			}	

			m_table_players [ i ]->resetPlayerStatus();
#ifdef SHOW_DETIAL 		
			WL(LL_DEV ,"table_id = %d is game over uid = %u gold = %lld \n",m_table_id, m_table_players [ i ]->get_user_id(), game_end_data.result_info [ i ].balance  );
#endif
		}
		game_end_data.result_info [ i ].ticket = 0 ;
	}
#ifdef SHOW_DETIAL 

	WL(LL_DEV ,"table_id = %d is game over winner = %d player = %u totalxzgold = %d\n",m_table_id ,winner ,m_table_players [ winner ]->get_user_id() ,totalxzgold  );

#endif
	
	//发送数据
	StreamPacketBuilder::instance()->notifyGameOver( this , &game_end_data, m_game_logic );
	clearScene();
	m_total_coin			= 0 ;

	//如果真人加机器人 人数在4个或以上则退出一到二个机器人
	int robotleavenum = 0;
	if ( m_total_players == 4 )
	{
		robotleavenum = 1;
	}
	else if ( m_total_players == 5 )
	{
		robotleavenum = 2;
	}
	//printf( "zq robotleave number = %d\r\n", robotleavenum );
	for ( BYTE i = 0 ; i < TABLE_CHAIR_COUNT; i++) 
	{
		if ( robotleavenum > 0 )
		{
			if( (m_table_players[i]) && (m_table_players[i]->isNormalPlayer() == false) )
			{
				//printf( "zq leave  robot = %x\r\n", m_table_players[i] );
				m_table_players[i]->get_handler()->sendPacket( MSG_ROBOT_LEAVE_MSG, NULL, 0 );
				robotleavenum--;
			}
		}
	}
}

void NormalTable::clearScene()
{
	for ( BYTE i = 0 ; i < GAME_PLAYER; i++) {
		if ( m_table_players [ i ] ){
			Player * player = m_table_players [ i ];
			m_table_players [ i ]->resetPlayerStatus();
			if(i != m_table_players [ i ]->get_chair_id() || m_table_id != m_table_players [ i ]->get_table_id())  //!������Ч��λ��
			{
				//WL(LL_WARNING,"i != player->get_chair_id() userID::%d  table_id = %d  i:%d  get_chair_id:%d  get_table_id:%d \n",player->get_user_id(), m_table_id, i, player->get_chair_id(), player->get_table_id());
				m_table_players[ i] = NULL;
				if(player->get_handler())
				{
					bool isok = false;
					isok = player->get_handler()->isClosed();
					WL(LL_INFO, "nUserID:%d player->get_chair_id()  isClosed :%d \n", isok);
				}
				continue;
			}
			if ( player->get_handler()  ) //清掉断线用户
			{
				FrontClientHandler * handler = player->get_handler() ;
				if ( handler->isClosed() ){
					WL(LL_WARNING,"player=%u check close and leave chair chair id:%d\n",player->get_user_id() , player->get_chair_id());
					StreamPacketBuilder::instance()->notifyStatusChange( this , m_table_players [ i ] , STATUS_LEAVE_CHAIR ) ;
					playerLeaveTable( player );
					CloseConnsList::instance()->release( handler );
					continue;
				}
			}
			int diff = time(NULL) - player->m_game_status_time ;
			if ( diff < 0 || diff >= 600 )
			{
				WL(LL_WARNING,"player=%u go out\n",player->get_user_id() );
				StreamPacketBuilder::instance()->notifySystemPleaseLeave( player );
				StreamPacketBuilder::instance()->notifyStatusChange( this , player , STATUS_LEAVE_CHAIR , i );
				player->m_play_free_time = 0 ;
				playerLeaveTable( player );
			}
		}

	}
}
bool NormalTable::isCurrChair( BYTE chair )
{
	return ( m_curr_chair == chair ) ;
}

BYTE NormalTable::nextChair(BYTE currChair)
{
	BYTE next_chair = INVALID_CHAIR ;
	//不为空，再找下一个不为空的
	for ( BYTE i = 1 ; i <= TABLE_CHAIR_COUNT ; i++){
		BYTE chair =  ( currChair + i ) % TABLE_CHAIR_COUNT ;
		if ( currChair != chair && m_table_players [ chair ] 
			&& m_table_players [ chair ]->isPlaying() ){
				next_chair = chair ;
				break;
		}
	}

	return next_chair ;
}

void NormalTable::printChairInfo(int next_chair)
{
	for ( BYTE i = 0 ; i < TABLE_CHAIR_COUNT ; i++){
		if (m_table_players [ i ] && m_table_players [ i ]->isPlaying() ){
			WL(LL_DEV, "table_id=%d, cur_chair=%d, player=%u, sit=%d, CurrRound=%d, CurrCoin=%d, Dealer=%d, TotalCoin=%d \n",
				m_table_id, next_chair, m_table_players[i]->get_user_id(), i, getCurrRound(), getCurrCoin(), getTotalCoin() );
		}
	}
}

void NormalTable::setDeader()
{
	/*m_banker_user = rand() % TABLE_CHAIR_COUNT ;
	if ( m_table_players [ m_banker_user ] != NULL ) return ;*/
	
	BYTE chairs [ TABLE_CHAIR_COUNT ] ;
	BYTE count = 0 ;
	for ( BYTE i = 0 ; i < TABLE_CHAIR_COUNT ;i++ ){
		if ( m_table_players [ i ] && m_table_players [ i ]->isPlaying() ) {
			//chairs [ count ++ ] = m_table_players [ i ]->get_chair_id() ; //!��ֹ�û����ϵ�chairid �����������id ��ƥ�� 
			chairs [ count ++ ] = i;
		}
	}
	if ( (m_banker_user == INVALID_CHAIR) || (m_banker_user < 0 || m_banker_user >= TABLE_CHAIR_COUNT) )
	{
		if ( count > 0 )
		{
			m_banker_user = chairs [ rand() % count ];
		}
		else 
		{
			m_banker_user = 0 ;
		}
	}
}

void NormalTable::operaTimeout()
{
	if ( isPlaying() )
	{
		if ( vaildChair( m_curr_chair ) )
		{
			Player * player = getPlayer( m_curr_chair ) ;
			if ( player )
			{
				WL(LL_DEV ,"table_id = %d player = %u operatimeout and giveup \n",m_table_id ,player->get_user_id()   );
				
				//放弃处理
				this->giveup( player );
			}
		}
	}
	
}

void NormalTable::handleCmpCard( Packet * packet , Player * player )
{
	BYTE	second_chair = (BYTE)*((BYTE*)packet->getData()) ;
	if ( vaildChair( second_chair ) && getPlayer( second_chair ) )
	{
		this->cmpCard( player ,getPlayer( second_chair ) ) ;
	}
}

void NormalTable::handleAddScore( Packet * packet ,Player * player )
{
	StreamReader reader( (BYTE*)packet->getData() );
	int gold		= reader.get_int();
	BYTE  times		= reader.get_byte();
	BYTE  is_add	= reader.get_byte();
	addScore( player , gold , is_add, times );
}

void NormalTable::resetRound()
{
	
	if ( m_curr_chair == m_start_round_chair )
	{
		m_current_round ++ ;
		m_current_round = m_current_round >=  m_room_config->max_round ? m_room_config->max_round : m_current_round ;
	}
	//printf( "m_curr_chair : %d  m_start_round_chair : %d m_current_round = %d\r\n", m_curr_chair, m_start_round_chair, m_current_round );
}

void NormalTable::checkStart()
{
	//在游戏过程中时
	if ( isPlaying() ) {
		return ;
	}
	//m_timer.cleanup();//没有玩家,清除定时器
	if ( m_ready_count == TABLE_CHAIR_COUNT )
	{
		gameStart(); //所有人都准备
		return ;
	}
	if ( m_ready_count >= 2 ){			//2个人以上准备好
		//定时5秒开始游戏
		if (!m_timer.is_enable_timer())
		{
			m_timer.start_timer(&NormalTable::gameStart , Config::instance()->m_timeouts.game_start_second * 1000 ); 
		}

	}else {			//1个人或没有人准备好
		m_timer.cleanup();
		//启动踢人定时器
		//m_kick_timer.start_timer(&NormalTable::kickPlayer , Config::instance()->m_timeouts.drop_player_second * 1000 ); 
	}

	#if 0
	for ( BYTE i = 0 ; i < GAME_PLAYER; i++)
	{
		if ( m_table_players [ i ] )
		{
			Player * player = m_table_players [ i ];
			if(i != m_table_players [ i ]->get_chair_id() || m_table_id != m_table_players [ i ]->get_table_id())  //!???????
			{
				WL(LL_WARNING," checkStart i != player->get_chair_id() userID::%d  table_id = %d  i:%d  get_chair_id:%d  get_table_id:%d \n"\
					,player->get_user_id(), m_table_id, i, player->get_chair_id(), player->get_table_id());
				m_table_players[ i] = NULL;
			}
		}
	}
	#endif 
#ifdef SHOW_DETIAL 

	WL(LL_DEBUG ," table_id = %d ready = %d count = %d\n",m_table_id ,m_ready_count , m_total_players );
#endif
}

void NormalTable::startOperaTimer()
{
	m_timer.start_timer(&NormalTable::operaTimeout , Config::instance()->m_timeouts.player_timeout * 1000);
}

void NormalTable::kickPlayer()
{
	if ( isPlaying() ) 
	{
		m_kick_timer.cleanup();
	}
	
}

void NormalTable::recordPlayerLost( Player * player )
{
	const char * proc_name = "sp_writeNormalRecord";
	if ( !player->isNormalPlayer() ){
		proc_name = "sp_writeRobotRecord";
	}
	INT64 coin = 0;

	if (player->get_user_gold() < player->getTableCoin()) {
		INT64 tmp_coin = (INT64)player->get_user_gold();
		coin = -tmp_coin;
	}
	else {
		coin = player->getTableCoin() == 0 ? 0 : - player->getTableCoin();
	}

	BYTE player_chair = player->get_chair_id();
	if (player_chair >= 0 && player_chair < TABLE_CHAIR_COUNT && m_table_players[player_chair] == player) {
		setMaxCards(player, m_player_card_data[player_chair]);
	}
	int max_card_num = player->getUserInfo().max_card[0] + player->getUserInfo().max_card[1]*100 + player->getUserInfo().max_card[2]*10000;
	player->OnPlayerLost();
	char cardstr[8] = {0};
	BYTE *pcards = player->getCards();
	sprintf( cardstr, "%02x%02x%02x", pcards[0], pcards[1], pcards[2] );
	SQLReq * req = SQLMemoryPool::instance()->mallocReq( REQ_TYPE_EXECUTE_COMMOND ,NULL );
	req->id = player->get_user_id();
	snprintf( req->sql , sizeof(req->sql) ,"call %s(%lld, %u,%d,%lld,   %d,%d,%d,%d, %d, '%s', %d )",
		proc_name,m_gameid, player->get_user_id() ,
		m_room_config->room_id, player->get_user_gold(),
		coin ,0 , 0 , SCORE_KIND_LOST, 0, cardstr, max_card_num );
	//printf( "zq recordPlayerLost req->sql = %s\r\n", req->sql );
	player->add_user_gold( coin ) ;
#ifdef SHOW_DETIAL 

	WL(LL_INFO , "table_id = %d player = %u lost balance = %lld desk = %d score = %d\n", m_table_id ,player->get_user_id() ,player->get_user_gold() ,player->getTableCoin() ,coin  );
#endif

	DataBaseReadThreadPool::instance()->pushQueue( req );

}

void NormalTable::OnGameOverPlayerLost( Player * player, Player * win_player )
{
	//WL(LL_INFO , "OnGameOverPlayerLost 1111 \n" );
	if (player == NULL || win_player == NULL)
		return;

	if (player == win_player)
		return;

	if (!player->isNormalPlayer())
		return;

	int coin = 0;

	if (player->get_user_gold() < player->getTableCoin()) {
		int tmp_coin = (int)player->get_user_gold();
		coin = tmp_coin;
	}
	else {
		coin = player->getTableCoin() == 0 ? 0 : player->getTableCoin();
	}

	player->OnGameOver(win_player, coin);

	//WL(LL_INFO , "OnGameOverPlayerLost 222 coin = %d \n", coin );
}

//winscore: 达到某个值则发喇叭
void NormalTable::recordPlayerWin( Player * player ,  int coin , int tax , int ticket, int winscore )
{
	//printf("recordPlayerWin = %d\n", coin);
	const char * proc_name = "sp_writeNormalRecord";
	if ( !player->isNormalPlayer() ){
		proc_name = "sp_writeRobotRecord";
	}

	BYTE player_chair = player->get_chair_id();
	if (player_chair >= 0 && player_chair < TABLE_CHAIR_COUNT && m_table_players[player_chair] == player) {
		setMaxCards(player, m_player_card_data[player_chair]);
		int card_type = m_game_logic.get_card_type_sort(m_player_card_data[player_chair], MAX_COUNT);
		if ( winscore > 0 )
		{
			player->OnWinMoney(winscore, card_type);
		}
	}
	int max_card_num = player->getUserInfo().max_card[0] + player->getUserInfo().max_card[1]*100 + player->getUserInfo().max_card[2]*10000;
	player->OnPlayerWin();
	char cardstr[8] = {0};
	BYTE *pcards = player->getCards();
	sprintf( cardstr, "%02x%02x%02x", pcards[0], pcards[1], pcards[2] );
	SQLReq * req = SQLMemoryPool::instance()->mallocReq(REQ_TYPE_EXECUTE_COMMOND ,NULL );
	req->id = player->get_user_id();
	snprintf( req->sql , sizeof(req->sql) ,"call %s( %lld, %u,%d,%lld,%d,%d,%d,%d,%d,'%s', %d )",
		proc_name,m_gameid, player->get_user_id() ,
		m_room_config->room_id, player->get_user_gold(),
		coin ,ticket , tax ,SCORE_KIND_WIN, 0, cardstr, max_card_num );
	player->add_user_gold( coin ) ;
	player->add_user_ticket( ticket ) ;
	DataBaseReadThreadPool::instance()->pushQueue( req );

	//printf("recordPlayerWin sql:%s \n", req->sql);
	//printf("1:%d  2:%d 3:%d \n", player->getUserInfo().max_card[0], player->getUserInfo().max_card[1], player->getUserInfo().max_card[2]);
}
bool NormalTable::exit_card( BYTE card [] ){
	for ( BYTE i = 0 ; i < GAME_PLAYER ; i++)
	{
		if ( m_table_players [ i ] ){
			for ( BYTE j = 0 ; j < MAX_COUNT ; j++)
			{
				if ( card [ j ] == m_player_card_data [ i ] [ 0 ] ||
					card [ j ] == m_player_card_data [ i ] [ 1 ] || 
					card [ j ] == m_player_card_data [ i ] [ 2 ] )
				{
					return true ;
				}
			}
		}
	}
	return false ;
}
bool NormalTable::sendGoodCards()
{
#if 0
	for ( int i = 0; i < 15; i++ )
	{
		int pos = i/3;
		if ( pos % 2 == 0 )
		{
			m_player_card_data[i/3][i%3] = ((0x01*(i%3))<<4) +  0x01 * (i/3 + 1);
		}
		else
		{
			m_player_card_data[i/3][i%3] = ((0x01*(i/3))<<4) +  0x05 + i%3;
		}

		
	}
	return true;
#endif
	RoomControlCards *proomcards = Config::instance()->get_room_control_crads( m_room_config->room_id );
	//printf( "m_room_config->room_type = %d proomcards = %x\r\n", m_room_config->room_id, proomcards );
	if ( proomcards )
	{
		int randunmlist[5] = {0};
		GoodCardManager good_card_manager;
		good_card_manager.InitGoodCards( proomcards->delminnum, (int*)proomcards->delmaxrate );
		for ( BYTE i = 0 ; i < GAME_PLAYER ; i++)
		{
			int randnum = rand()%10000;
			randunmlist[i] = randnum;
			if ( m_table_players [ i ] == NULL )
			{
				continue;
			}
			int playnum = m_table_players[i]->getUserInfo().user_score.win_count + m_table_players[i]->getUserInfo().user_score.lost_count;
			int cardstype = 0;
			//从第几局开始
			int startpos = 0;
			for ( int j = 0; j < 5; j++  )
			{
				if ( playnum <= proomcards->playcount[j] )
				{
					startpos = proomcards->startpos[j];
					break;
				}
			}
			good_card_manager.GetCardsFromList( startpos, m_player_card_data[i] );
			//printf( "zq startpos = %d playnum = %d cards: %02x %02x %02x\r\n", startpos, playnum, m_player_card_data[i][0], m_player_card_data[i][1], m_player_card_data[i][2] );
		}
		//int totalnum = test_card_num[0] + test_card_num[1] + test_card_num[2] + test_card_num[3] + test_card_num[4] + test_card_num[5];
		//printf( "zq ====goodcards rate: %d %d %d %d %d %d  number:", test_card_num[0],test_card_num[1],test_card_num[2],test_card_num[3],test_card_num[4],test_card_num[5] );
		//printf( "%d %d %d %d %d %d ", randunmlist[0],randunmlist[1],randunmlist[2],randunmlist[3],randunmlist[4],randunmlist[5] );
		//printf( " %d %d %d %d %d %d\r\n", test_card_num[0]*100/totalnum,test_card_num[1]*100/totalnum,test_card_num[2]*100/totalnum,test_card_num[3]*100/totalnum,
		//	test_card_num[4]*100/totalnum,test_card_num[5]*100/totalnum );
	}
	return false ;
}

void taskFinish( const DWORD user_id , TaskItem * item ){
	SQLReq * req = SQLMemoryPool::instance()->mallocReq( REQ_TYPE_DDL ,NULL );
	snprintf( req->sql , sizeof(req->sql) ,"call p_finish_task(%u,%d,%d)",
		user_id , item->task_id,item->task_range );
	//printf( "zq taskFinish sql: %s\r\n", req->sql );
	DataBaseCommitThread::instance()->push( req );
}
void taskFinish( const DWORD user_id , TASK_TYPE type )
{
	TaskItem * item = TaskManager::instance()->get_task( type );
	if ( item != NULL )
	{
		return taskFinish( user_id , item );
	}
}

void NormalTable::finishTask()
{
	TaskItem * task = TaskManager::instance()->m_task_daily_play_round;
	Player * player = NULL ;
	for ( BYTE i = 0 ; i < TABLE_CHAIR_COUNT ; i++){
		player = m_table_players [ i ] ;
		if ( player  ){
			if ( player->isIndle() ) {
				player->m_play_free_time ++ ;
			}
			else{
				player->set_play_times( player->get_play_times() + 1 );
				player->m_play_free_time = 0 ;
				if ( task && player->get_play_times() == task->round  ){
					taskFinish( player->get_user_id() , TASK_TYPE_DAILY_COMPLETE_10_ROUND );
				}
				else{
					//
					TaskItem * task = TaskManager::instance()->finishDayTask( player->get_play_times() ) ;
					if ( task  ) taskFinish( player->get_user_id() , task );
				}
			}
		}
	}
}
void NormalTable::systemGiveTicket( BYTE first_chair, BYTE second_chair,  BYTE card_type [ ] ){

#define		BAOZI_TICKET	1
#define		SHUNJIN_TICKET	2

	if ( card_type [ 0 ] == CT_BAO_ZI ) //是豹子类型，送多少
	{
		m_ticket [ first_chair ] =  BAOZI_TICKET ; //豹子类型，送10张奖券
	}else if ( card_type [ 0 ] == CT_SHUN_JIN )
	{
		m_ticket [ first_chair ] =  SHUNJIN_TICKET ;//同花顺金花类型，送2张奖券
	}
	if ( card_type [ 1 ] == CT_BAO_ZI ) //是豹子类型，送多少
	{
		m_ticket [ second_chair ] =  BAOZI_TICKET ; //豹子类型，送10张奖券
	}else if ( card_type [ 1 ] == CT_SHUN_JIN )
	{
		m_ticket [ second_chair ] =  SHUNJIN_TICKET ;//同花顺金花类型，送2张奖券
	}

}

int NormalTable::rewardTicket( Player * winPlayer , int tax  )
{
	TaskItem * task_item = TaskManager::instance()->m_tasks_normal_win ;
	int ticket = 0 ;
	BYTE chair = winPlayer->get_chair_id() ;
	if ( task_item && winPlayer  )
	{
		ticket = tax * task_item->task_ticket / 10000 ;
		if ( ticket > 0 )
		{
			if ( m_ticket [ chair ] == BAOZI_TICKET ){
				task_item			= TaskManager::instance()->m_tasks_baozi_win ;
			}else if (  m_ticket [ chair ] == SHUNJIN_TICKET ){
				task_item			= TaskManager::instance()->m_tasks_shunjin_win ;
			}
			if ( task_item  ) { 
				int n				= round( ticket * task_item->task_ticket / 10000 ) ;
				ticket				+= n ;
			}
			if ( ticket > Config::instance()->m_global_config.max_ticket )
			{
				ticket = Config::instance()->m_global_config.max_ticket ;
			}
		}
	}
	return ticket ;
}


void NormalTable::handleRewardOnlineCoin( Packet * packet ,Player * player )
{
	if  (packet == NULL || player == NULL)
		return;

	StreamReader reader( packet->getData() );
	BYTE  is_need_reward = reader.get_byte(); 
	int diff = time(NULL) - player->m_stay_table_time ;

	UserInfo & refuser = player->getUserInfo();

	int onlinerewardnum = Config::instance()->m_online_reward_confs.size();
	//
	int curcount = (refuser.today_get_online_count >= onlinerewardnum) ? onlinerewardnum - 1 : refuser.today_get_online_count;
	int add_gold = Config::instance()->m_online_reward_confs[curcount].coin;
	int	time_sc = Config::instance()->m_online_reward_confs[curcount].minute;
	int awardid = Config::instance()->m_online_reward_confs[curcount].conf_id;
	if (is_need_reward != 1)//不等于是只查询
	{
		OnlineRewardResult relt;
		relt.result = RESULT_FAILD;
		relt.recvtime = (time_sc <= diff) ? 0 : (time_sc-diff);
		if ( refuser.today_get_online_count >= onlinerewardnum  )
		{
			//今天领取完了
			relt.coin = 0;
			relt.canrecv = false;
		}
		else
		{
			relt.coin = add_gold;
			relt.canrecv = true;
		}
		StreamPacketBuilder::instance()->handleOnlineReward(player, &relt);
		return;
	}

	OnlineRewardResult relt;
	if ( refuser.today_get_online_count >= onlinerewardnum  )
	{
		//今天领取完了
		relt.result = RESULT_FAILD;
		relt.canrecv = false;
		relt.coin = 0;
		relt.recvtime = 0;
	}
	else
	{
		relt.canrecv = true;
		if (diff < time_sc)
		{
			relt.result = RESULT_FAILD;
			time_sc -= diff;
			relt.coin = add_gold;
			relt.recvtime = time_sc;
		}
		else 
		{
			relt.result = RESULT_OK;
			player->m_stay_table_time = time(NULL);
			refuser.today_get_online_count++;
			curcount = refuser.today_get_online_count;
			//已领取完
			if ( refuser.today_get_online_count >= onlinerewardnum  )
			{
				relt.canrecv = false;
				relt.recvtime = 0;
				relt.coin = add_gold;
			}
			else
			{
				relt.recvtime = Config::instance()->m_online_reward_confs[curcount].minute;
				relt.coin = add_gold;
			}
			player->set_user_gold(refuser.user_score.gold + add_gold);

			//通知数据库修改领取记录
			SQLReq * req = SQLMemoryPool::instance()->mallocReq(REQ_TYPE_ONLINE_REWARD , player->get_handler() );
			req->id = player->get_user_id();
			snprintf( req->sql , sizeof(req->sql) ,"call p_write_online_reward(%d,%d,%d,%d)",
				player->get_user_id() ,awardid , time_sc, add_gold );
			//printf("zq task player =%d req online reward sql=%s  player=%x\n",player->get_user_id(),req->sql, player );
			DataBaseReadThreadPool::instance()->pushQueue( req );
		}
	}
	
	StreamPacketBuilder::instance()->handleOnlineReward(player, &relt);
	StreamPacketBuilder::instance()->notifyUpdatePlayerGold(player->getTable(), player);
}

void NormalTable::handleUseProps( Packet * packet ,Player * player )
{
	StreamReader reader( packet->getData() );
	BYTE	prop_id	= reader.get_byte(); //道具ID
	BYTE	to		= reader.get_byte() ;//to
	switch ( prop_id )
	{
	case PROP_TYPE_KICK:
		handleKickPlayer( packet , player );
		break;
	case PROP_TYPE_CHARGE_CARD:
		break;

	}
}

void NormalTable::handleKickPlayer( Packet * packet ,Player * player )
{
	/*if ( isPlaying() )
	{
		//游戏已开始不能T人
		StreamPacketBuilder::instance()->respError( player ,MSG_RSP_KICK_PLAYER ,ERR_T_GAME_START );
		return ;
	}*/
	StreamReader reader( packet->getData() );
	int	dstuid		= reader.get_uint() ;//被T用户ID
	Player * dstPlayer = NULL;
	int dsttableid = 0;
	FrontClientHandler * dsthandler = ActiveConnsList::instance()->find( dstuid );
	if ( (!dsthandler) || (!dsthandler->getPlayer()) )
	{
		StreamPacketBuilder::instance()->respError( player ,MSG_RSP_KICK_PLAYER, ERR_T_PLAYER_LEAVE );
		return;
	}
	dstPlayer = dsthandler->getPlayer();
	dsttableid = dstPlayer->get_table_id();
	if ( dsthandler->getPlayer()->isPlaying() )
	{
		//游戏已开始不能T人
		StreamPacketBuilder::instance()->respError( player ,MSG_RSP_KICK_PLAYER ,ERR_T_GAME_START );
		return;
	}

	if ( dstuid == getTableOwner() )
	{
		StreamPacketBuilder::instance()->respError( player ,MSG_RSP_KICK_PLAYER ,ERR_T_IS_OWNER );
		return;
	}

	int kickviplevel = Config::instance()->m_vip_kicklevel;
	
	//printf( "zq player->getUserInfo().viplevel = %d kickviplevel = %d dsttableid = %d  dsthandler = %x\r\n", player->getUserInfo().viplevel, kickviplevel, dsttableid, dsthandler );
	//判断玩家自己的vip
	if ( player->getUserInfo().viplevel < kickviplevel )
	{
		StreamPacketBuilder::instance()->respError( player ,MSG_RSP_KICK_PLAYER ,ERR_T_LESS_VIP_LEVEL );
		return;
	}
	//用户金币数是否够用
	int usegold = 10000;
	map< int , GameDataConfig >::iterator iter = Config::instance()->m_gamedataconfig.find( DATA_CONFIG_T_PLAYER_GOLD );
	if ( iter != Config::instance()->m_gamedataconfig.end() )
	{
		usegold = iter->second.valuelist[0];
	}
	//printf( "player->get_user_enable_gold() = %lld\r\n", player->get_user_enable_gold() );
	if ( player->get_user_enable_gold() < usegold + m_room_config->lower_limit_gold )
	{
		StreamPacketBuilder::instance()->respError( player ,MSG_RSP_KICK_PLAYER ,ERR_T_LESS_GOLD );
		return;
	}
	
	if ( (dstPlayer) && (dsttableid == player->get_table_id())  )
	{
		//vip等级是否大于被T玩家等级
		//printf( "player->getUserInfo().viplevel =%d  dstPlayer->getUserInfo().viplevel = %d\r\n", player->getUserInfo().viplevel , dstPlayer->getUserInfo().viplevel );
		if ( player->getUserInfo().viplevel <= dstPlayer->getUserInfo().viplevel )
		{
			StreamPacketBuilder::instance()->respError( player ,MSG_RSP_KICK_PLAYER ,ERR_T_LESS_PLAER_LEVEL );
			return;
		}
		//更新数据库数据
		SQLReq * req = SQLMemoryPool::instance()->mallocReq( REQ_TYPE_UPDATE_WEALTH , NULL );
		req->id = player->get_user_id();
		snprintf( req->sql , sizeof(req->sql) ,"call SP_UpdateUserWealth(%u,%d,%d, 17)",
			player->get_user_id() , -10000, 0 );
		DataBaseReadThreadPool::instance()->pushQueue( req );

		player->set_user_gold( player->get_user_gold() - usegold);
		StreamPacketBuilder::instance()->notifyKickPlayer( this , player , dstPlayer );
		StreamPacketBuilder::instance()->notifyStatusChange( this, dstPlayer, STATUS_LEAVE_CHAIR, dstPlayer->get_chair_id() );
		StreamPacketBuilder::instance()->notifyUpdatePlayerGold( this , player);
		playerLeave( dstPlayer );
		checkStart();
	}
	else
	{
		//玩家已离开
		StreamPacketBuilder::instance()->respError( player ,MSG_RSP_KICK_PLAYER ,ERR_T_PLAYER_LEAVE );
	}
}

void NormalTable::handleTextChat( Packet * packet ,Player * player )
{
	if (player == NULL)
		return;

	if (m_room_config->room_id == ROOM_CONFI_ID_1 )
	{
		if ((player->get_user_win_count() + player->get_user_lost_count()) < 3)
		{
			StreamPacketBuilder::instance()->respError(player, MSG_NOTIFY_NEWER_TALK_LIMIT, 0);
			return;
		}
	}
	StreamPacketBuilder::instance()->notifyUserChat( this , player , packet->getData() , packet->getDataLen() );
}

bool NormalTable::playerLeave( Player * player )
{
	for ( BYTE i = 0 ; i < TABLE_CHAIR_COUNT ; i++){
		if ( m_table_players [ i ] == player  ){
			playerLeaveTable( player );
			return true ;
		}
	}
	return false ;
}


void NormalTable::handleOnlineRewardConf( Packet * packet ,Player * player )
{
	StreamPacketBuilder::instance()->respOnlineRewardConf( player );
}

void NormalTable::handleOnlineRewardStatus( Packet * packet ,Player * player )
{
	StreamPacketBuilder::instance()->respOnlineRewardStatus( player );
}

void NormalTable::resetRunInfo()
{
	m_total_players			= 0 ;
	m_real_playernum		= 0	;
	m_ready_count			= 0 ;
	m_playing_count			= 0 ;
	for ( BYTE i = 0 ; i < TABLE_CHAIR_COUNT ; i++)
	{
		if ( m_table_players [ i ] )
		{
			m_playing_count +=  m_table_players [ i ]->isPlaying() ? 1 : 0 ;
			m_total_players ++ ;
			m_ready_count	+= !isPlaying() && m_table_players [ i ]->isReady() ? 1 : 0 ;
			if ( m_table_players[i]->isNormalPlayer() )
			{
				m_real_playernum++;
			}
		}
	}
}

void NormalTable::systemGiveCoin( Player * player )
{
	//if ( player->get_give_times() > 0 && player->get_user_gold() < Config::instance()->m_global_config.system_give_gold )
	//{
	//	int coin = Config::instance()->m_global_config.system_give_gold - player->get_user_gold() ;
	//	WL(LL_DEV ,"player gold( %u) < m_limit_gold(%d) and times=%d coin = %d\n",
	//		player->get_user_gold() , m_room_config->lower_limit_gold,player->get_give_times() , coin);
	//	player->set_give_times( player->get_give_times() - 1 );
	//	
	//	StreamPacketBuilder::instance()->notifySystemGiveCoin( player ,coin );

	//	SQLReq * req = SQLMemoryPool::instance()->mallocReq(REQ_TYPE_DDL , player->get_handler() );
	//	snprintf( req->sql , sizeof(req->sql) ,"call p_give_user_gold(%u,%d,%u,%d)",
	//		player->get_user_id() ,m_room_config->room_id, player->get_user_gold(),coin );
	//	player->add_user_gold( coin ) ;
	//	DataBaseCommitThread::instance()->push( req );
	//}
}


void NormalTable::playerLeaveTable( Player * player )
{
	if(!player)
		return;
	BYTE chair = player->get_chair_id() ;
	
	if(chair >= TABLE_CHAIR_COUNT)
	{
		WL(LL_ERROR,"table_id = %u player = %u chair = %d  > TABLE_CHAIR_COUNT \n", m_table_id, player->get_user_id(), chair);
		return;
	}
	
	if ( player != m_table_players [ chair ] )
	{
		int tableuser = 0;
		int tablechair = -1;
		if (m_table_players [ chair ])
		{
			tableuser = m_table_players [ chair ]->get_user_id();
			tablechair = m_table_players [ chair ]->get_chair_id();
		}
		WL(LL_ERROR,"table_id = %d player = %u chair = %d table player = %u and chair = %d\n",
			m_table_id , player->get_user_id() , chair , tableuser , tablechair );
		return ;
	}
	if ( player->get_chair_id() == m_banker_user )
	{
		m_banker_user = INVALID_CHAIR;
	}
	if ( player->isReady() ) m_ready_count -- ;
	player->leave();
	if ( m_table_players[chair]->isNormalPlayer()  )
	{
		if ( m_real_playernum > 0 )
		{
			m_real_playernum--;
		}
	}
	m_table_players [ chair ] = NULL ;
	m_total_players -- ;

#ifdef SHOW_DETIAL 

	WL(LL_WARNING, "table_id = %u player = %u   m_table_players[%u] is NULL  player addr:0x%02x\n", m_table_id, player->get_user_id(), chair, player);
#endif

	if(! player->get_handler())
		return;

	if(GameLotteryNew::instance()->isPlayerInBetStatus(player->get_user_id()) ==  false)
	{
		player->get_handler()->changeUserOnlineStatus(0,player->get_user_id());
	}
}

void NormalTable::setMaxCards( Player * player , BYTE cards [ 3 ])
{
	if ( player->getUserInfo().max_card [ 0 ] ==  '\0' ){
		memcpy( player->getUserInfo().max_card ,cards , 3 ) ;
	}else{
		//比较
		BYTE card_type [ 4 ];
		bool ret = m_game_logic.compare_card( player->getUserInfo().max_card ,cards ,MAX_COUNT , card_type);
		if ( !ret ){
			memcpy( player->getUserInfo().max_card ,cards , 3 ) ;
		}
	}

	BYTE cardtype = m_game_logic.get_card_type_sort(cards, MAX_COUNT);
	switch (cardtype)
	{
	case CT_SHUN_JIN:
		player->OnGetShunjin();
		break;
	case CT_BAO_ZI:
		player->OnGetBaozi();
		break;
	default:
		break;
	}
}

bool NormalTable::hasAllIn()
{
	if ( m_playing_count == 2 )
	{
		for (BYTE i = 0; i < GAME_PLAYER; i++){
			if ( m_table_players[ i ] && m_table_players[ i ]->isPlaying() &&  m_table_players[ i ]->isAllIn()  ) {
				return true ;
			}
		}
	}
	return false ;
}

void NormalTable::roundOver()
{
	if ( m_current_round >= m_room_config->max_round && m_playing_count >= 2 )
	{
		WL(LL_INFO,"m_current_round = %d m_playing_count = %d roundOver\n",m_current_round , m_playing_count );
		while ( 1 )
		{
			Player * player [ 2 ] = { 0 };
			if ( getCmpPlayers( player ) )
			{
				BYTE card_type [ 2 ] ;
				Player * lostPlayer	= NULL ;
				bool ret = m_game_logic.compare_card( player[ 0 ]->getCards() ,player[ 1 ]->getCards() ,MAX_COUNT , card_type);
				if ( ret ){ //0赢
					lostPlayer = player[ 1 ] ;
				}else{
					lostPlayer = player[ 0 ] ;
				}
				lostPlayer->lost(); // 失败
				recordPlayerLost( lostPlayer );
			}
			else
			{
				this->gameOver();
				break;
			}
		}
	}
}

bool NormalTable::getCmpPlayers( Player * player[] )
{
	BYTE cn = 0 ;
	for ( BYTE i = 0 ; i < TABLE_CHAIR_COUNT && cn < 2  ; i++)
	{
		if ( m_table_players [ i ] && m_table_players [ i ]->isPlaying() )
		{
			player [ cn ++ ] = m_table_players [ i ] ;
		}
	}
	return cn >= 2 ;
}

//付费表情
void	NormalTable::handleReqPayExpress( Packet * packet ,Player * player )
{
	int limitmingold = m_room_config->lower_limit_gold;
	StreamReader reader( packet->getData() );
	BYTE userchirdid = reader.get_int();
	int objectchirdid = reader.get_int();
	BYTE expressid = reader.get_byte();
	BYTE count = reader.get_byte();
	INT64 gold = player->get_user_enable_gold();
	int usecount = (count == 0) ? 1 : 10;
	map< int , GameDataConfig >::iterator iter = Config::instance()->m_gamedataconfig.find( DATA_CONFIG_EXPRESS_GOLD );
	int oneexpressgold = 100;
	if ( iter != Config::instance()->m_gamedataconfig.end() )
	{
		oneexpressgold = iter->second.valuelist[0];
	}
	if ( gold - usecount*oneexpressgold > limitmingold )
	{
		gold = gold - usecount*oneexpressgold;
		StreamPacketBuilder::instance()->notifyExpress( this , player , packet->getData() , packet->getDataLen(), -usecount*oneexpressgold );
		//更新用户金币
		player->getUserInfo().user_score.gold -= usecount*oneexpressgold;
		StreamPacketBuilder::instance()->notifyUpdatePlayerGold( this, player );
		//通知数据库修改用户金币
		SQLReq * req = SQLMemoryPool::instance()->mallocReq( REQ_TYPE_USE_EXPRESS , player->get_handler() );
		req->id = player->get_user_id();
		snprintf( req->sql , sizeof(req->sql) ,"call SP_Use_Express( %u, %d, %d, %d, %d)",
			player->get_user_id(), objectchirdid,  expressid, -usecount*100, usecount );
		//printf( "zq handleReqPayExpress req->sql = %s\r\n", req->sql );
		DataBaseReadThreadPool::instance()->pushQueue( req );
	}
	
}



int	NormalTable::GetCardsTypeByRate( int ratenum, DWORD * goodcardratelist )
{
	int totalsection = 0;
	for ( int i = 0; i < 6; i++ )
	{
		totalsection += goodcardratelist[i];
		if ( ratenum < totalsection )
		{
			test_card_num[(6 - i)-1]++;			
			return (6 - i);//1单牌 -- 6豹子
		}
	}
	return CT_SINGLE;
}





















//////////////////////////////////////////////////////////////////////////////////////////////////////////////
void PrivateTable::set_table_info( const char * name , const char * pwd , DWORD base_gold , DWORD user_id )
{
	BYTE len = strlen( name );
	len	= len > sizeof(m_table_info.room_name) - 1 ? sizeof(m_table_info.room_name) - 1 : len ;
	memcpy( m_table_info.room_name , name , len );
	m_table_info.room_name [ len ] = '\0';
	len = strlen( pwd );
	len	= len > TABLE_PASSWORD_LEN - 1 ? TABLE_PASSWORD_LEN - 1 : len ;  
	memcpy( m_table_info.table_password , pwd , len );
	m_table_info.table_password [ len ] = '\0';
	m_table_info.base_gold				= base_gold ;
	setBaseGold( base_gold );
	m_table_info.apply_time				= time(NULL);
	m_table_info.user_id				= user_id;
}

PrivateTable::PrivateTable()
{

}

PrivateTable::~PrivateTable()
{
	if (m_room_config)
		delete m_room_config;
}

void PrivateTable::InitRoomConfig(RoomConfigItem * pRoomConfig)
{
	if (pRoomConfig == NULL)
		return;

	m_room_config = new RoomConfigItem();
	if (m_room_config == NULL)
		return;

	memcpy(m_room_config, pRoomConfig, sizeof(RoomConfigItem));
}

void PrivateTable::clearTable()
{
	if ( this->getPlayerCount() <= 0 && m_table_info.user_id > 0 )
	{
		SQLReq * req = SQLMemoryPool::instance()->mallocReq( REQ_TYPE_EXECUTE_COMMOND , NULL );
		req->id = m_table_info.user_id;
		snprintf( req->sql , sizeof(req->sql) ,"delete  from priv_playing_tables where user_id = %d", m_table_info.user_id );
		DataBaseReadThreadPool::instance()->pushQueue( req );

		m_table_info.room_name [ 0 ]		= '\0';
		m_table_info.table_password [ 0 ]	= '\0';
		m_table_info.base_gold				=  0 ;
		m_table_info.user_id				=  0 ;
	}
}
